﻿using System.IO;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.UI;

public class CombineTextures : MonoBehaviour
{
    public GameObject Go;
    public RawImage Img;

    void Start()
    {
        for (int i = 0; i < this.Go.transform.childCount; i++)
        {
            Texture tex = Resources.Load((i + 1).ToString()) as Texture;
            this.Go.transform.GetChild(i).GetComponent<MeshRenderer>().sharedMaterial.mainTexture = tex;
        }

        this.CombineTex();
    }

    private void CombineTex()
    {
        List<Texture2D> textures = new List<Texture2D>();
        MeshRenderer[] renders = this.Go.GetComponentsInChildren<MeshRenderer>();
        for (int i = 0; i < renders.Length; i++)
        {
            textures.Add((Texture2D) renders[i].sharedMaterial.mainTexture);
        }

        if (textures.Count > 0)
        {
            Texture2D tempTex = new Texture2D(1024, 1024);
            Rect[] uvs = tempTex.PackTextures(textures.ToArray(), 0);
            tempTex.Apply();

            Texture2D rCombineTex = new Texture2D(tempTex.width, tempTex.height, TextureFormat.ARGB32, false);
            rCombineTex.SetPixels32(tempTex.GetPixels32());
            rCombineTex.Apply();

            Debug.Log("combine textures finish.");
            this.Img.texture = rCombineTex;
            this.CombineMesh(textures.ToArray(), rCombineTex, uvs);

        }
    }

    private void CombineMesh(Texture2D[] texs, Texture2D mainTex, Rect[] rect)
    {
        GameObject combineGo = new GameObject("CombineGo");
        combineGo.transform.position = new Vector3(5, 0, 0);
        List<Vector2[]> usList = new List<Vector2[]>();
        MeshFilter[] allFilter = this.Go.GetComponentsInChildren<MeshFilter>();
        MeshRenderer[] allRender = this.Go.GetComponentsInChildren<MeshRenderer>();
        CombineInstance[] combineMesh = new CombineInstance[allFilter.Length];
        Material[] materials = new Material[allFilter.Length];
        for (int i = 0; i < allFilter.Length; i++)
        {
            materials[i] = allRender[i].sharedMaterial;
            combineMesh[i].mesh = allFilter[i].sharedMesh;
            combineMesh[i].transform = allFilter[i].transform.localToWorldMatrix;
            usList.Add(allFilter[i].sharedMesh.uv);
        }

        MeshFilter combineFilter = combineGo.AddComponent<MeshFilter>();
        MeshRenderer combineRender = combineGo.AddComponent<MeshRenderer>();
        combineFilter.sharedMesh = new Mesh();
        combineFilter.sharedMesh.CombineMeshes(combineMesh);
        Vector2[] uv = new Vector2[combineFilter.sharedMesh.vertices.Length];

        int count = 0;
        for (int i = 0; i < usList.Count; i++)
        {
            for (int filter_index = 0; filter_index < allFilter.Length; filter_index++)
            {
                float scaleX = ((float) (texs[filter_index].width) / mainTex.width);
                float scaleY = ((float) (texs[filter_index].height) / mainTex.height);
                for (int j = 0; j < allFilter[filter_index].sharedMesh.vertices.Length; j++)
                {
                    uv[count] = new Vector2(
                        (float) (rect[filter_index].xMin + allFilter[filter_index].sharedMesh.uv[j].x * scaleX),
                        (float) (rect[filter_index].yMin + allFilter[filter_index].sharedMesh.uv[j].y * scaleY));
                    count++;
                }
            }

            combineFilter.sharedMesh.uv = uv;
            combineRender.sharedMaterial = Instantiate(materials[0]);
            combineRender.sharedMaterial.mainTexture = mainTex;
            Debug.Log("combine mesh finish.");
        }
    }
}
